﻿using Avalonia.Controls.Notifications;
using Avalonia.Threading;
using Notification = Ursa.Controls.Notification;
using WindowNotificationManager = Ursa.Controls.WindowNotificationManager;

namespace Digitalmes.AvaloniaUI.ViewModels;

public sealed partial class SerialPortsDemoViewModel : ViewModelBase, IDisposable
{
    private readonly CancellationTokenSource _cts = new();

    private readonly IMessageQueue<SerialPortMessage> _messageQueue;

    private WindowNotificationManager? _notificationManager;

    /// <summary>
    /// 扫入的条码
    /// </summary>
    [ObservableProperty]
    private string? _barcode = "2101771-PT307:0S23589:R724001";

    /// <summary>
    /// 操作人
    /// </summary>
    [ObservableProperty]
    private string? _operator;

    /// <summary>
    /// 扫码日志记录
    /// </summary>
    [ObservableProperty]
    private ObservableCollection<LogMessage> _messageLogs = [];

    [RelayCommand]
    private async Task Submit(CancellationToken cancellationToken)
    {
        // 延迟执行
        await Task.Delay(300, cancellationToken);

        if (string.IsNullOrWhiteSpace(Barcode))
        {
            Notice("条码为空", "请输入条码内容", NotificationType.Warning);
            Barcode = "";
            return;
        }

        try
        {
            // 提交业务逻辑

            Notice("提交成功", Barcode, NotificationType.Success);
            AddLog($"零件码：{Barcode}，操作人：{Operator}");
            Barcode = ""; // 提交后清空条码
        }
        catch (Exception ex)
        {
            Notice("提交失败", Barcode, NotificationType.Error);
            AddLog(ex.Message, NotificationType.Error);
        }
    }

    public SerialPortsDemoViewModel(IMessageQueue<SerialPortMessage> messageQueue)
    {
        _messageQueue = messageQueue;

        Polling();
    }

    private void Polling()
    {
        _ = Task.Run(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                var message = await _messageQueue.DequeueAsync();

                // 在 UI 线程上开始作业并立即返回
                Dispatcher.UIThread.Post(() =>
                {
                    Barcode = message.Content;
                });
            }
        });
    }

    private void AddLog(string? message, NotificationType messageType = NotificationType.Information)
    {
        if (MessageLogs.Count > 32)
        {
            MessageLogs.RemoveAt(MessageLogs.Count - 1);
        }

        var msg = $"{DateTime.Now:MM/dd HH:mm:ss}\t{message}";
        var msgType = messageType switch
        {
            NotificationType.Warning => "Warning",
            NotificationType.Error => "Danger",
            _ => "",
        };
        MessageLogs.Insert(0, new LogMessage(msg, msgType));
    }

    /// <summary>
    /// 界面显示通知消息
    /// </summary>
    private void Notice(string? title, string? content, NotificationType notificationType)
    {
        AttemptAttachNotificationManager();

        _notificationManager?.Show(
            new Notification(title, content),
            notificationType,
            expiration: TimeSpan.FromSeconds(5),
            showClose: false,
            classes: ["Light"]);
    }

    private void AttemptAttachNotificationManager()
    {
        if (_notificationManager == null && TopLevel != null)
        {
            _notificationManager = new WindowNotificationManager(TopLevel)
            {
                Position = NotificationPosition.TopCenter,
                MaxItems = 3,
            };
        }
    }

    public void Dispose()
    {
        _cts.Cancel();
        _notificationManager?.Uninstall();
    }
}

public record LogMessage(string Message, string MessageType);
